參考資料
我覺得自己文章標題取有夠爛,沒什麼美感又超白話哈哈,這篇是個獨立的單元講述動態組建的建立和切換,沒有使用到之前的程式碼。
按鈕1: 按下取得部落格已發佈的文章
按鈕2: 按下取得垃圾桶文章
開始製作 (粗糙版) : 雖不同於 Vue.js 官網所提供的範例,但是透過以下的步驟,將可以迅速地知道怎麼切換組件。
const postedArticle = {
name: 'postedArticle',
template: `
<div>
<div v-for="post in posts" :key="post.id">{{ post.article }}</div>
</div>
`,
data () {
return {
posts: [{ article: '正常文章1', id: 1 }, { article: '正常文章2', id: 2 }]
}
}
}
const postedArticle = {
name: 'postedArticle',
template: `
<div>
<div v-for="post in posts" :key="post.id">{{ post.article }}</div>
</div>
`,
data () {
return {
posts: [{ article: '垃圾文章1', id: 1 }, { article: '垃圾文章2', id: 2 }]
}
}
}
重要提示,本教學僅為製作步驟及原理參考,且僅提供思路,不代表最佳實踐
兩個組件結構一模一樣 ,這裡只是為文章方便,所以寫成小組件模擬文章的模式,實際上較好的作法並不是寫成這種小組件,因為template的部分沒有語法高量以及emmet的支援 ( 維護上比較麻煩 ) ,而是應該將兩個組件個別做為不同的 ( 或相同的,看怎麼設計,比如文章的部分應該用非同步呼叫 API 的方式取得文章列表後放入 posts ) .vue 檔案來進行更加細部的功能封裝。
<button type="button" @click = "currentComponent=postedArticle">取得正常文章</button>
<button type="button" @click = "currentComponent=trashArticle">取得垃圾文章</button>
<component :is="currentComponent">
透過按鈕註冊click事件來改變 currentComponent
,即可進行組件的切換,而這邊是整段代碼的設定:
<template>
<button type="button" @click = "currentComponent=postedArticle">取得正常文章</button>
<button type="button" @click = "currentComponent=trashArticle">取得垃圾文章</button>
<component :is="currentComponent"></component>
</template>
<script>
const postedArticle = { 以下略 }
const trashArticle= { 以下略 }
export default {
name: 'testCase',
data () {
return {
currentComponent: postedArticle, // 這裡預設一開始顯現普通文章
postedArticle: postedArticle,
trashArticle: trashArticle
}
}
}
</script>
關鍵:
使用 <component>
tag 並綁定 :is="自定義的組件名稱"
隨後透過我們自己的任意方式且在任意時機變更 自定義的組件名稱
以達成組件切換。
點下取得不同文章時,若我們用call API的方式實作,可以在等待的途中加入類似Loading的特效,讓使用者知道系統正在讀取中,避免因文章的讀取空白時間過長,讓使用者誤會系統沒反應。
開始製作 (官網改寫版) : 在知道關鍵點後,我們就可以來一步步拆解官網提供的範例 並改寫成我們的版本,假如忘記關鍵是什麼,請稍微往上再看一下關鍵的敘述...
同粗糙版
const postedArticleForVersion = {}
const trashArticleForVersion = {}
const draftForVersion = {}
tabs
,由於按鈕是v-for="tab in tabs"
來渲染,所以按鈕數量將取決於tabs陣列的長度。<template>
<div>
<button
v-for="tab in tabs"
v-bind:key="tab"
v-on:click="currentTab = tab"
>
{{ tab }}
</button>
</div>
</template>
<script>
export default {
data () {
return {
currentTab: "正常文章", // 預設顯示正常文章
tabs: ['正常文章', '廢棄文章']
}
}
}
</script>
// 做到以上結束,會有兩個按鈕
currentComponent
所存放的組件。<button type="button" @click = "currentComponent=postedArticle">取得正常文章</button>
<button type="button" @click = "currentComponent=trashArticle">取得垃圾文章</button>
<component :is="currentComponent">
// 我們這段類似官網,比較自動化,如此可以透過不斷增加tabs的長度來新增按鈕, v-for="tab in tabs" 這是Vue中用來遍歷陣列內容的方法,tab從第0個元素開始
// 而v-for是掛在button上,所以最終會依照tabs的長度分別渲染該次迴圈值給 {{ tab }} , 到這裡為止你的畫面依照tabs陣列的順序變成2個按鈕了
插播注意 ! 官網範例中使用以下computed 計算屬性來偵聽 button 點按改變currentTab 後的方式來切換組件,我們的版本不會使用這樣的方式。
<template>
<component v-bind:is="currentTabComponent" class="tab"></component>
</template>
<script>
// ...vue實例內
computed: {
currentTabComponent: function() {
return "tab-" + this.currentTab.toLowerCase();
}
}
</script>
結束插播,回到本範例
<button v-for="tab in tabs"
:key="tab.id"
@click="currentComponentForVersion = tab.id" >
{{ tab.title }}
</button>
tabs: [
{ title: '正常文章', id: 'postedArticleForVersion' },
{ title: '廢棄文章', id: 'trashArticleForVersion' },
{ title: '草稿', id: 'draftForVersion' }
]
現在你的畫面變三個按鈕,並且之前 Vue 實例內的 data 屬性 currentTab: "正常文章",
已經沒用了,請刪除之。
我們這裡切換組件的方法並不像官網一樣使用 computed 屬性偵測更換,而是在渲染按鈕的時候將變更組件的動作如同粗糙版一樣綁在click事件中,個人認為比額外寫在 computed 中還要具有可讀性。
接著在button下方加入關鍵 <component :is="currentComponentForVersion"></component>
,現在可以成功的切換組件了。咦 ?但是現在按了什麼反應都沒有啊 ,別急,還記得我們三個小組件現在還是空白的嗎?現在我們要來開始撰寫組件內容了,以下是我們要使用的組件內容,先看一組就好。
const postedArticleForVersion = {
name: 'postedArticleForVersion',
template: `
<div class="container-article">
<div class="container-list">
<div v-for="post in posts" @click="articleSelected = post.article">
{{ post.title }}
</div>
</div>
<div class="container-article__show">
{{ articleSelected }}
</div>
</div>
`,
data () {
return {
posts: [
{ title: '正常文章1', article: '正常文章內容1', id: 1, show: false },
{ title: '正常文章2', article: '正常文章內容2', id: 2, show: false },
{ title: '正常文章3', article: '正常文章內容3', id: 3, show: false }
],
articleSelected: null
}
}
}
div.container-article
包裹者兩個分別為div.container-list
、 div.container-article__show
div.container-list
內部有 <div v-for="post in posts"
及 {{ post.title }}
負責渲染代表標題的div
區塊,而@click="articleSelected = post.article
的部分負責指定當下迴圈索引寫入的文章內容。div.container-article__show
負責顯示使用者選擇的標題內文注意 ,div.container-list
所渲染出的 div
區塊,可以是<a>
、或者使用<li>
包裹在有序或無序清單內或者其他方案,此處僅僅為展示內容方便,因此通通使用 div
標籤,其具體結構及CSS請自行依照情況不同斟酌變化。
posts
的部分而已。const trashArticleForVersion = {
name: 'trashArticleForVersion',
template: `
<div class="container-article">
<div class="container-list">
<div v-for="post in posts" @click="articleSelected = post.article">
{{ post.title }}
</div>
</div>
<div class="container-article__show">
{{ articleSelected }}
</div>
</div>
`,
data () {
return {
posts: [
{ title: '垃圾文章1', article: '垃圾文章內容1', id: 1 },
{ title: '垃圾文章2', article: '垃圾文章內容2', id: 2 },
{ title: '垃圾文章3', article: '垃圾文章內容3', id: 1 }
],
articleSelected: null
}
}
}
const draftForVersion = {
name: 'trashArticleForVersion',
template: `
<div class="container-article">
<div class="container-list">
<div v-for="post in posts" @click="articleSelected = post.article">
{{ post.title }}
</div>
</div>
<div class="container-article__show">
{{ articleSelected }}
</div>
</div>
`,
data () {
return {
posts: [
{ title: '草稿1', article: '草稿內容1', id: 1 },
{ title: '草稿2', article: '草稿內容2', id: 2 },
{ title: '草稿3', article: '草稿內容3', id: 1 }
],
articleSelected: null
}
}
}
把三個組件的內容補完後,接下來就會得到如下可切換文章分類,且可點選不同文章內容的功能了。
並且應該發現到切換組件的關鍵就算到的官方改寫版,也依然是文始提及的:
關鍵:
使用 <component>
tag 並綁定 :is="自定義的組件名稱"
隨後透過我們自己的任意方式且在任意時機變更 自定義的組件名稱
以達成組件切換。
<keep-alive></keep-alive>
把 <component :is></component>
包住 ,如此之前的資料就會被快取起來,再點回去的時候資料就不會重新渲染變空了本教程到此結束,請再次注意,一般來說不會在一個頁面像這樣定義這麼多小組件,本教程不代表最佳做法,僅僅展示如何切換組件。
https://codepen.io/fiftybillionHuang/pen/gOrWQEw
沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列